package com.ruisi.thumbnail;

import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;


/**
 * 缩率图管理器
 * 本管理器采用三层的缩率图缓存结构
 * 1.内存缓存       --- 内存中缓存图片，避免io频繁导致程序卡，采用LRUCache
 * 2.本地存储器缓存  --- 在sd卡或者内存卡中缓存，对于从网络上拉回来的图片可以避免重复拉取,只有通过url下载的图片才有2级缓存，图片下载下来存储
 *                    在本地缓存目录下，文件名为该图片的url的md5值
 * 3.网络下载图片    --- 1、2级缓存中都没有的图片，才考虑从网络中下载，下载之后对图片进行1、2级缓存
 * @author spring ming
 *
 */
public class ThumbnailManager {
	public interface ImageLoadListener{
		void onImageLoadSuccess(String imgUrlOrPath, Bitmap bitmap);
		void onImageLoadFailed(String imgUrlOrPath, int errCode);
	}
	
	@SuppressLint("HandlerLeak")
	private class CallbackHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case BitmapDecodeRunnable.IMAGE_LOAD_FAIL:
			{
				DecodeTask task = (DecodeTask)msg.obj;
				ImageLoadListener l = task.mListenerRef.get();
				if(null != l){
					l.onImageLoadFailed(task.mLocalPath, msg.arg1);
				}
				break;
			}
			case BitmapDecodeRunnable.IMAGE_LOAD_SUCCESS:
			{
				DecodeTask task = (DecodeTask)msg.obj;
				ImageLoadListener l = task.mListenerRef.get();
				if(null != l){
					mLruCache.put(task.mLocalPath, task.mBitmap);
					l.onImageLoadSuccess(task.mLocalPath, task.mBitmap);
				}
				break;
			}
			case DownloadRunnable.DOWNLOAD_FAIL:
			{
				DownloadTask task = (DownloadTask)msg.obj;
				ImageLoadListener l = task.mListenerRef.get();
				if(null != l){
					l.onImageLoadFailed(task.mDownloadUrl, msg.arg1);
				}
				break;
			}
			case DownloadRunnable.DOWNLOAD_SUCCESS:
			{
				DownloadTask task = (DownloadTask)msg.obj;
				ImageLoadListener l = task.mListenerRef.get();
				if(null != l){
					mLruCache.put(task.mDownloadUrl, task.mBitmap);
					l.onImageLoadSuccess(task.mDownloadUrl, task.mBitmap);
				}
				break;
			}
			default:
				break;
			}
		}
	}
	
	/**
	 * 错误码
	 */
	public static final int ERR_URL_ILIGEAL = 1;  // 非法的url
	
	
	public static final int ERR_FILE_NOT_EXSIST = 2; 
	
	
	
	/**
	 * 构造函数
	 * @param context
	 */
	public ThumbnailManager(Context context) {
		super();
		
		mContext   = context;
		mCachePath = getDefaultCachePath();
	}
	
	
	/**
	 * 通过这个函数获取默认的图片管理器
	 * 也可以新建几个ThumbnailManager,具体根据业务情况定
	 * @return
	 */
	public static synchronized ThumbnailManager defaultManager(Context context){
		if(null == defaultManager){
			defaultManager = new ThumbnailManager(context);
		}
		
		return defaultManager;
	}
	
	/**
	 * 设置缓存目录
	 * 
	 * @param path
	 */
	public synchronized void setCachePath(String path){
		if(!path.endsWith("/")){
			mCachePath = path + "/";
		}else{
			mCachePath = path;
		}
	}
	
	/**
	 * 通过图片url获取图片
	 * @param url
	 * @param listener 
	 * @return 如果图片在本地，则直接返回，否则则异步下载网络图片
	 */
	public Bitmap getRemoteImage(String url, ImageLoadListener listener){
		Bitmap bitmap = mLruCache.get(url);
		if(null == bitmap){
			String path = mCachePath  + "/" + getMD5(url);
			DownloadTask task = new DownloadTask(url, path, listener);
			DownloadRunnable downloadRunnable = new DownloadRunnable(task, mCallbackHandler);
			mThreadPool.submit(downloadRunnable);
		}		
		return bitmap;
	}
	
	/**
	 * 通过本地路径获取图片
	 * @param localPath
	 * @return
	 */
	public Bitmap getLocalImage(String localPath, ImageLoadListener listener){
		Bitmap bitmap = mLruCache.get(localPath);
		if(null == bitmap){
			DecodeTask task = new DecodeTask(localPath, listener);
			BitmapDecodeRunnable decodeRunnable = new BitmapDecodeRunnable(task, mCallbackHandler);
			mThreadPool.submit(decodeRunnable);
		}
		
		
		return bitmap;
	}
	
	
	// 缓存目录的名字
	private static final String CACHE_DIR_NAME = "Thumbnail";
	
	// 默认的管理器
	private static ThumbnailManager defaultManager = null;
	
	
	private Context mContext;
	
	// 缓存目录
	private String mCachePath;
	
	// 内存中的缓存
	private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(50);
	
	// 下载图片的线程池
	private ExecutorService mThreadPool = Executors.newFixedThreadPool(5);
	
	private CallbackHandler mCallbackHandler = new CallbackHandler();
	
	static char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
	private String getMD5(String url){
		String md5 = null;
		MessageDigest md;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			return md5;
		}
		
		byte[] result = md.digest(url.getBytes());
		int j = result.length;
        char str[] = new char[j * 2];
        int k = 0;
        for (int i = 0; i < j; i++)
        {
        	byte byte0 = result[i];
            str[k++] = hexDigits[byte0 >>> 4 & 0xf];
            str[k++] = hexDigits[byte0 & 0xf];
        }
        md5 = new String(str);
		
		return md5;
	}
	
	/**
	 * 获取默认的缓存目录
	 * 默认的缓存目录为/data/data/xxx/cache/$CACHE_DIR_NAME
	 * @return
	 */
	private String getDefaultCachePath(){
		String path = null;
		
		File cacheDir = mContext.getCacheDir();
		path = cacheDir.getAbsolutePath() + "/" + CACHE_DIR_NAME ;
		
		File f = new File(path);
		f.delete();
		if(!f.exists()){
			f.mkdir();
		}
		
		return path;
	}

}
